package twoD.IsoPfem.EmbededCrackModels;

import inf.jlinalg.BLAM;
import inf.jlinalg.GeneralMatrixLSESolver;
import inf.jlinalg.ILSESolver;
import inf.jlinalg.IMatrix;
import inf.jlinalg.IVector;
import inf.jlinalg.QuadraticMatrixInfo;
import inf.jlinalg.SolveFailedException;
import inf.text.ArrayFormat;

import java.util.ArrayList;

import oneD.fem.algorithm.MyLinalg;

public class LoadController {

	private static final double INITIAL_GAMMA = 1e-10;

	private CrackStructure cStruct_;
	private int numberOfSteps_;
	private double stepSize_;

	private ArrayList<CrackingState> state_;

	public LoadController(CrackStructure struct) {
		cStruct_ = struct;
		initialization();
	}

	public void setNumberOfStep(int n) {
		numberOfSteps_ = n;
	}

	public void setStepSize(double s) {
		stepSize_ = s;
	}

	public void initialization() {
		state_ = new ArrayList<CrackingState>();
		int numNode = cStruct_.getMesh().getNumberOfNodes();
		int numElem = cStruct_.getNumberOfElements();
		CrackingState s0 = new CrackingState(numNode, numElem);
		s0.setDisplacement(0.0);
		s0.setGamma(INITIAL_GAMMA);
		s0.setZeroCrack();
		state_.add(s0);
	}

	public void Iterate() {
		// solver initialization
		ILSESolver solver = new GeneralMatrixLSESolver(
				GeneralMatrixLSESolver.SOLVER_IMPL_JAVA);
		QuadraticMatrixInfo aInfo = solver.getAInfo();
		IMatrix kGlobal = solver.getA();

		int NEQ = cStruct_.enumerateDOFs();
		double[] rGlobal0 = new double[NEQ];
		double[] rGlobal = new double[NEQ];
		aInfo.setSize(NEQ);

		int numNode = cStruct_.getMesh().getNumberOfNodes();
		int numElem = cStruct_.getNumberOfElements();

		cStruct_.assembleExternalForceVector(rGlobal0);

		int it = 0;

		do {
			// find the displacement of the structure
			solver.initialize();
			System.out.println("Analysis tracking step: " + (it + 1));
			BLAM.zero(kGlobal);// clear ktGlobal to fill in new data
			cStruct_.assembleTangentStiffnessMatrix(state_.get(it), kGlobal, true);
//			System.out.println("system stiffness matrix = "
//					+ MatrixFormat.format(kGlobal));
			rGlobal = rGlobal0.clone();
			MyLinalg.scale(1.0 + it * stepSize_, rGlobal);

			try {
				solver.solve(rGlobal);
			} catch (SolveFailedException e) {
				System.out.println(e.toString());
			}
			// at this point, rGlobal is d(n+1)
			cStruct_.setDisplacement(rGlobal);
			System.out.println("system displacement vector = "
					+ ArrayFormat.format(rGlobal));

			// checking crack initiation condition
			double sigmamax = cStruct_.checkCrackInitiationCondition();
			System.out.println("Maximum stress = " + sigmamax);

			// compute crack opening parameters and compliance parameter for
			// cracked element
			double[] gamma = state_.get(it).getGamma().clone();
			IVector[] e = state_.get(it).getCrackOpeningParameters().clone();
			cStruct_.updateCrackingState(gamma, e);

			// store the results to the state
			CrackingState s = new CrackingState(numNode, numElem);
			s.setDisplacement(cStruct_.getU());
			s.setGamma(gamma);
			s.setCrack(e);
			state_.add(s);

			// advance to next step
			it++;
			System.out.println();
			System.out.println("------------------------------------------");
		} while (it < numberOfSteps_);
	}
}
